package com.解释器模式;

import java.util.Objects;
import java.util.Stack;

/**
 * @author Fang Ruichuan
 * @date 2022-12-22 20:01
 */
public class CalculatorContext {
    private final Stack<IExpression> stack = new Stack<>();

    public CalculatorContext(String expression) {
        this.parse(expression);
    }

    // 解释器表达式
    private void parse(String expression) {
        String[] elements = expression.split(" ");
        IExpression aExpr, bExpr;

        for (int i = 0, length = elements.length; i < length; i++) {
            String operator = elements[i];
            if (CalculatorContext.isOperator(operator)) {
                aExpr = this.stack.pop();
                System.out.println("出栈: " + aExpr.interpret());
                bExpr = new NumNonterminalExpression(Integer.parseInt(elements[++i]));
                TerminalExpression res = CalculatorContext.util(aExpr, bExpr, operator);
                this.stack.push(res);
                System.out.println("计算: " + aExpr.interpret() + operator + bExpr.interpret());
                System.out.println("计算结果: " + Objects.requireNonNull(res).interpret() + "入栈");
            } else {
                NumNonterminalExpression numNonterminalExpression = new NumNonterminalExpression(Integer.parseInt(elements[i]));
                this.stack.push(numNonterminalExpression);
                System.out.println("入栈: " + numNonterminalExpression.interpret());
            }
        }
    }

    // 计算结果
    public int calculate() {
        int interpret = this.stack.pop().interpret();
        System.out.println("计算结果：" + interpret + "出栈");
        return interpret;
    }

    public static TerminalExpression util(IExpression a, IExpression b, String symbol) {
        if ("+".equals(symbol)) {
            return new AddNonterminalExpression(a, b);
        } else if ("-".equals(symbol)) {
            return new SubNonterminalExpression(a, b);
        } else {
            return null;
        }
    }

    public static boolean isOperator(String symbol) {
        return ("+".equals(symbol) || "-".equals(symbol));
    }
}
